package foodmaterial.service.impl;

import foodmaterial.action.OrderAction;
import foodmaterial.dao.CustomerDao;
import foodmaterial.dao.DocumentTrackDao;
import foodmaterial.dao.FoodMaterialDao;
import foodmaterial.dao.OrderDao;
import foodmaterial.dto.*;
import foodmaterial.entity.*;
import foodmaterial.service.OrderService;
import foodmaterial.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl extends BaseService implements OrderService {

    @Autowired
    private OrderDao dao ;

    @Autowired
    private CustomerDao customerDao ;

    @Autowired
    private FoodMaterialDao foodMaterialDao ;

    @Autowired
    private DocumentTrackDao documentTrackDao ;

    private int setMealsTypeTemplateDetails(MealsTypeTemplate mealsTypeTemplate) {
        List<MealsTypeTemplateDetails> details = mealsTypeTemplate.getDetails() ;
        if (details == null || details.isEmpty()) return 0 ;
        for (MealsTypeTemplateDetails detail : details) {
            detail.setId(nextId());
            detail.setTemplateId(mealsTypeTemplate.getId());
        }
        return 1 ;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addMealsTypeTemplate(MealsTypeTemplate mealsTypeTemplate) {
        mealsTypeTemplate.setId(nextId());
        if (setMealsTypeTemplateDetails(mealsTypeTemplate) == 0) return 0 ;
        dao.insertMealsTypeTemplate(mealsTypeTemplate) ;
        return dao.insertMealsTypeTemplateDetails(mealsTypeTemplate.getDetails()) ;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int modifyMealsTypeTemplate(MealsTypeTemplate mealsTypeTemplate) {
        if (setMealsTypeTemplateDetails(mealsTypeTemplate) == 0) return 0 ;
        dao.deleteMealsTypeTemplateDetails(mealsTypeTemplate.getId()) ;
        dao.updateMealsTypeTemplate(mealsTypeTemplate);
        return dao.insertMealsTypeTemplateDetails(mealsTypeTemplate.getDetails()) ;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeMealsTypeTemplate(Long id) {
        dao.deleteMealsTypeTemplateDetails(id) ;
        return dao.deleteMealsTypeTemplate(id);
    }

    @Override
    public List<MealsTypeTemplate> queryMealsTypeTemplate(MealsTypeTemplateDto dto) {
        return dao.selectMealsTypeTemplate(dto);
    }

    @Override
    public CalculateExceedResult calculateExceed(CalculateExceedDto dto) {
        List<FoodMaterial> foodMaterials = dao.selectCalculateExceed(dto.getFoodMaterialId()) ;
        List<CalculateExceedResult.Result> results = new ArrayList<>() ;
        BigDecimal totalMoney = new BigDecimal("0.00") ;
        for (int i = 0; i < foodMaterials.size() ; i++) {
            FoodMaterial foodMaterial = foodMaterials.get(i);
            CalculateExceedResult.Result result = new CalculateExceedResult.Result() ;
            result.setName(foodMaterial.getName());
            result.setSalePrice(foodMaterial.getSalePrice());
            result.setAmount(dto.getAmount().get(i));
            BigDecimal amount = new BigDecimal(dto.getAmount().get(i) + "");
            result.setTotal(Arithmetic.mul(
                    Arithmetic.div(amount,new BigDecimal(foodMaterial.getExpressionUnit()),4),foodMaterial.getSalePrice(),2));
            results.add(result) ;
            totalMoney = Arithmetic.add(totalMoney,result.getTotal(),2) ;
        }

        CalculateExceedResult calculateExceedResult = new CalculateExceedResult() ;
        calculateExceedResult.setTotalMoney(totalMoney);
        calculateExceedResult.setResults(results);
        if (dto.getStandard().compareTo(totalMoney) == -1) calculateExceedResult.setExceed(Boolean.TRUE);
        return calculateExceedResult;
    }

    @Override
    public List<MealsTypeTemplateDetails> queryMealsTypeTemplateDetails(Long id) {
        return dao.selectMealsTypeTemplateDetails(id);
    }

    @Override
    public List<FoodMaterial> queryMealsTypeTemplateDetailsBySupply(MealsTypeTemplateDetailsDto dto) {
        return dao.selectMealsTypeTemplateDetailsBySupply(dto);
    }

    @Override
    public List<FoodMaterial> queryMealsTypeTemplateDetailsByVipSupply(MealsTypeTemplateDetailsDto dto) {
        return dao.selectMealsTypeTemplateDetailsByVipSupply(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addCustomerTeam(CustomerTeam customerTeam) {
        customerTeam.setId(nextId());
        List<CustomerTeamDetails> data = customerTeam.getDetails() ;
        for (CustomerTeamDetails d : data) {
            d.setId(nextId());
            d.setCustomerTeamId(customerTeam.getId());
        }
        dao.insertCustomerTeam(customerTeam) ;
        return dao.insertCustomerTeamDetails(data);
    }

    @Override
    public int modifyCustomerTeam(CustomerTeam customerTeam) {
        return dao.updateCustomerTeam(customerTeam) ;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeCustomerTeam(Long id) {
        dao.deleteCustomerTeam(id) ;
        return dao.deleteCustomerTeamDetailsByTeamId(id);
    }

    @Override
    public List<CustomerTeam> queryCustomerTeam(CustomerTeam customerTeam) {
        return dao.selectCustomerTeam(customerTeam);
    }

    @Override
    public List<CustomerTeamDetails> queryCustomerTeamDetails(Map<String,Object> params) {
        return dao.selectCustomerTeamDetails(params);
    }

    @Override
    public List<MealsType> queryCustomerTeamMealsType(CustomerTeam customerTeam) {
        return dao.selectCustomerTeamMealsType(customerTeam);
    }

    private List<FoodMaterial> prepare(List<OrdersDetail> detailAll) {
        Map<Long, Integer> singleMap =
                detailAll.stream().collect(Collectors.groupingBy(OrdersDetail::getFoodMaterialId,
                        Collectors.summingInt(OrdersDetail:: getTotalAmount)));
        List<FoodMaterial> result = new ArrayList<>() ;
        singleMap.forEach((k,v) -> {
            FoodMaterial fm = new FoodMaterial() ;
            fm.setId(k);
            fm.setAmount(new BigDecimal(v  * -1));
            result.add(fm) ;
        });
        return result ;
    }

    private String checkOrdersExist(OrderAction.TempOrderData data) {
        OrdersDto dto = new OrdersDto() ;
        dto.setEndEatDate(DateUtil.format(data.getEatDate(),Constants.DEFAULT_DATE_FORMAT));
        dto.setBeginEatDate(dto.getEndEatDate());
        dto.setMealsTypeId(Long.toString(data.getMealsTypeId().longValue()));
        List<Long> customers = new ArrayList<>() ;
        if (data.getCustomers() != null) {
            for (MealsType mt : data.getCustomers()) {
                customers.add(mt.getCustomerId());
            }
        } else {
            customers.add(data.getCustomerId()) ;
        }
        dto.setCustomerId(customers);
        List<Orders> result = dao.checkOrdersExist(dto) ;
        if (result != null && result.isEmpty() == false) {
            StringBuilder sb = new StringBuilder() ;
            for (Orders o : result) {
                sb.append("[").append(o.getCustomerName()).append("]在[")
                .append(DateUtil.format(o.getEatDate(),Constants.DEFAULT_DATE_FORMAT))
                .append("] , ");
            }
            sb.append(" 订单已经生成过了") ;
            return sb.toString();
        }
        return null ;
    }

    private void combineFoodMaterial(Map<Long,OrdersDetail> ordersDetailMap,
                                     List<RecipeTemplate> recipeTemplates) {
        for (RecipeTemplate rt : recipeTemplates) {
            for (RecipeTemplateDetails detail : rt.getDetails()) {
                if (ordersDetailMap.containsKey(detail.getFoodMaterialId())) {
                    OrdersDetail od = ordersDetailMap.get(detail.getFoodMaterialId()) ;
                    od.setAmount(od.getAmount() + detail.getAmount());
                } else {
                    OrdersDetail od = new OrdersDetail();
                    od.setOriginalProcess(detail.getOriginalProcess());
                    od.setAmount(detail.getAmount());
                    od.setSalePrice(detail.getSalePrice());
                    od.setBuyPrice(detail.getBuyPrice());
                    od.setFoodMaterialId(detail.getFoodMaterialId());
                    od.setExpressionUnit(detail.getExpressionUnit());
                    ordersDetailMap.put(detail.getFoodMaterialId(),od) ;
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addOrders(OrderAction.TempOrderData data) {
        if (Constants.ORDER_TYPE_SELF.equals(data.getOrderType()) ||
            Constants.ORDER_TYPE_VIP_SELF.equals(data.getOrderType())) {
            String exist = checkOrdersExist(data);
            if (exist != null) return exist ;
        }
        List<OrdersRecipe> ordersRecipeList = null ;
        List<OrdersRecipeDetails> ordersRecipeDetailsList = null;
        if (isKitchen()) {
            ordersRecipeList = new ArrayList<>() ;
            ordersRecipeDetailsList = new ArrayList<>() ;
            List<RecipeTemplate> recipeList = data.getRecipeDetails() ;
            Map<Long,OrdersDetail> ordersDetailMap = new HashMap<>() ;
            combineFoodMaterial(ordersDetailMap,recipeList);
            data.setDetails(new ArrayList<>(ordersDetailMap.values()));
        }
        List<OrdersDetail> detailAll = new ArrayList<>();
        Map<Long,Orders> orders = new HashMap<>() ;
        List<Long> ids = new ArrayList<>() ;
        BigDecimal amountOfMoney = null ;
        for (MealsType mt : data.getCustomers()) {
            Orders order = new Orders() ;
            order.setId(nextId());
            order.setEatDate(data.getEatDate());
            order.setMealPersons(mt.getMealPersons());
            order.setMealStandard(mt.getMealStandard());
            order.setCustomerId(mt.getCustomerId());
            order.setMealsTypeId(mt.getMealsTypeNameId());
            order.setOperationPerson(this.getSysUser().getId());
            order.setOperationDate(new Date());
            order.setStatus(Constants.ORDER_STATUS_NORMAL);
            order.setOrderType(data.getOrderType());
            orders.put(order.getCustomerId(),order) ;
            ids.add(order.getCustomerId()) ;
        }
        List<CustomerInfo> customerInfos = customerDao.selectCustomerInfoByIds(ids) ;
        for (int i = 0 ; i < customerInfos.size() ; i++) {
            CustomerInfo c = customerInfos.get(i) ;
            Orders o = orders.get(c.getId()) ;
            setOrders(o,c);
            amountOfMoney = new BigDecimal("0.00") ;
            //为每个客户生成食材明细
            for (OrdersDetail detail : data.getDetails()) {
                OrdersDetail od = new OrdersDetail() ;
                od.setId(nextId());
                od.setOrdersId(o.getId());
                od.setEatDate(o.getEatDate());
                od.setSupplyDate(o.getSupplyDate());
                od.setDistributionDate(o.getDistributionDate());
                od.setOrderType(o.getOrderType());
                od.setCustomerId(o.getCustomerId());
                od.setMealsTypeId(o.getMealsTypeId());
                if (isKitchen() == false) {
                    double integer = o.getMealPersons() * detail.getAmount() / (detail.getExpressionUnit() * 1.);
                    od.setTotalAmount((int) Math.ceil(integer));
                } else {
                    od.setTotalAmount(o.getMealPersons() * detail.getAmount());
                }
                od.setFoodMaterialId(detail.getFoodMaterialId());
                od.setBuyPrice(detail.getBuyPrice());
                od.setSalePrice(detail.getSalePrice());
                od.setAmount(detail.getAmount());
                od.setOriginalProcess(detail.getOriginalProcess());
                od.setTotal(Arithmetic.mul(detail.getSalePrice() , od.getTotalAmount() , 2));
                if (isKitchen() == false) amountOfMoney = Arithmetic.add(od.getTotal(),amountOfMoney,2) ;
                detailAll.add(od) ;
            }
            if (isKitchen() == false) o.setAmountOfMoney(amountOfMoney);//不是厨房模式
            else {//厨房：计算订单总价，并保存菜谱的食材明细
                List<RecipeTemplate> recipeList = data.getRecipeDetails() ;
                for (RecipeTemplate rt : recipeList) {
                    OrdersRecipe or = new OrdersRecipe() ;
                    or.setId(nextId());
                    or.setOrdersId(o.getId());
                    or.setRecipeTemplateId(rt.getId());
                    or.setCustomerId(o.getCustomerId());
                    or.setMealsTypeId(o.getMealsTypeId());
                    or.setEatDate(o.getEatDate());
                    or.setSupplyDate(o.getSupplyDate());
                    or.setDistributionDate(o.getDistributionDate());
                    or.setOrderType(o.getOrderType());
                    or.setPrice(rt.getPrice());
                    or.setTotalAmount(o.getMealPersons());
                    or.setTotal(Arithmetic.mul(new BigDecimal(or.getTotalAmount()) , rt.getPrice(),2));
                    amountOfMoney = Arithmetic.add(or.getTotal(),amountOfMoney,2) ;
                    ordersRecipeList.add(or) ;
                    for (RecipeTemplateDetails rtd : rt.getDetails()) {
                        OrdersRecipeDetails ord = new OrdersRecipeDetails() ;
                        ord.setId(nextId());
                        ord.setOrdersId(o.getId());
                        ord.setOrdersRecipeId(or.getId());
                        ord.setAmount(rtd.getAmount());
                        ord.setFoodMaterialId(rtd.getFoodMaterialId());
                        ord.setRecipeTemplateId(rt.getId());
                        ord.setSalePrice(rtd.getSalePrice());
                        ord.setBuyPrice(rtd.getBuyPrice());
                        ordersRecipeDetailsList.add(ord) ;
                    }
                }
                o.setAmountOfMoney(amountOfMoney);
            }
        }
        List<Orders> insertList = new ArrayList<>() ;
        insertList.addAll(orders.values()) ;
        dao.insertOrders(insertList) ;
        if (ordersRecipeList != null) {
            dao.insertOrdersRecipe(ordersRecipeList);
            dao.insertOrdersRecipeDetails(ordersRecipeDetailsList);
        }
        int result = dao.insertOrdersDetail(detailAll) ;
        if (result <= 0) return "生成订单失败" ;
        return null ;
    }

    private void setOrders(Orders orders,CustomerInfo c) {
        orders.setAreaMasterName(c.getAreaMasterName());
        orders.setDriver(c.getDriver());
        orders.setRouterId(c.getRouterId());
        orders.setSupplyTypeId(c.getSupplyTypeId());
        orders.setCustomerId(c.getId());
        orders.setSupplyTeam(c.getSupplyTeamId());
        orders.setSupplyDate(DateUtil.plus(orders.getEatDate(),c.getAheadTime() * -1));
        if (isKitchen()) orders.setDistributionDate(orders.getSupplyDate());
        else orders.setDistributionDate(DateUtil.plus(orders.getSupplyDate() , -1));
    }

    private void setOrders(Orders orders,Long customerId) {
        MealsTypeDto dto = new MealsTypeDto() ;
        dto.setCustomerId(customerId);
        dto.setMealsTypeNameId(orders.getMealsTypeId());
        MealsType mt = customerDao.selectMealsType(dto).get(0) ;
        orders.setMealPersons(mt.getMealPersons());
        orders.setMealStandard(mt.getMealStandard());
    }

    /**
     * 带下单
     * @param data
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addDirectOrders(OrderAction.TempOrderData data) {
        /*if (Constants.ORDER_TYPE_SELF.equals(data.getOrderType()) ||
                Constants.ORDER_TYPE_VIP_SELF.equals(data.getOrderType())) {
            String exist = checkOrdersExist(data);
            if (exist != null) return exist ;
        }*/
        Orders orders = new Orders() ;
        orders.setId(nextId());
        orders.setEatDate(data.getEatDate());
        orders.setOperationDate(new Date());
        orders.setMealsTypeId(data.getMealsTypeId());
        if (Constants.ORDER_TYPE_DIRECT.equals(data.getOrderType())) {
            orders.setOperationPerson(this.getSysUser().getId());
        }
        orders.setStatus(Constants.ORDER_STATUS_NORMAL);
        orders.setOrderType(data.getOrderType());
        setOrders(orders,data.getCustomerId());
        List<Long> ids = new ArrayList<>();
        ids.add(data.getCustomerId()) ;
        CustomerInfo c = customerDao.selectCustomerInfoByIds(ids).get(0) ;
        setOrders(orders,c) ;
        List<OrdersRecipe> ordersRecipeList = null ;
        List<OrdersRecipeDetails> ordersRecipeDetailsList = null;
        BigDecimal amountOfMoney = new BigDecimal("0.00");
        if (isKitchen()) {
            orders.setMealPersons(data.getMealPersons());
            ordersRecipeList = new ArrayList<>() ;
            ordersRecipeDetailsList = new ArrayList<>() ;
            List<RecipeTemplate> recipeList = data.getRecipeDetails() ;
            Map<Long,OrdersDetail> ordersDetailMap = new HashMap<>() ;
            for (RecipeTemplate rt : recipeList) {
                OrdersRecipe or = new OrdersRecipe() ;
                or.setId(nextId());
                or.setOrdersId(orders.getId());
                or.setRecipeTemplateId(rt.getId());
                or.setOrderType(orders.getOrderType());
                or.setPrice(rt.getPrice());
                or.setTotalAmount(rt.getTotalAmount());
                or.setTotal(Arithmetic.mul(new BigDecimal(or.getTotalAmount()) , rt.getPrice(),2));
                or.setCustomerId(orders.getCustomerId());
                or.setMealsTypeId(orders.getMealsTypeId());
                or.setEatDate(orders.getEatDate());
                or.setSupplyDate(orders.getSupplyDate());
                or.setDistributionDate(orders.getDistributionDate());
                amountOfMoney = Arithmetic.add(or.getTotal(),amountOfMoney,2) ;
                ordersRecipeList.add(or) ;
                for (RecipeTemplateDetails rtd : rt.getDetails()) {
                    OrdersRecipeDetails ord = new OrdersRecipeDetails() ;
                    ord.setId(nextId());
                    ord.setOrdersId(orders.getId());
                    ord.setOrdersRecipeId(or.getId());
                    ord.setRecipeTemplateId(rt.getId());
                    ord.setSalePrice(rtd.getSalePrice());
                    ord.setBuyPrice(rtd.getBuyPrice());
                    ord.setFoodMaterialId(rtd.getFoodMaterialId());
                    ord.setAmount(rtd.getAmount());
                    ordersRecipeDetailsList.add(ord) ;
                }
            }
            orders.setAmountOfMoney(amountOfMoney);
            combineFoodMaterial(ordersDetailMap,recipeList);
            data.setDetails(new ArrayList<>(ordersDetailMap.values()));
        }
        for (OrdersDetail detail : data.getDetails()) {
            detail.setId(nextId());
            detail.setOrdersId(orders.getId());
            if (data.getRecipeDetails() == null) {
                detail.setTotalAmount(detail.getAmount()); //不是厨房
            } else {
                detail.setTotalAmount(detail.getAmount() * orders.getMealPersons());
            }
            detail.setTotal(Arithmetic.mul(detail.getSalePrice(), detail.getTotalAmount(),2));
            detail.setEatDate(orders.getEatDate());
            detail.setMealsTypeId(orders.getMealsTypeId());
            detail.setSupplyDate(orders.getSupplyDate());
            detail.setDistributionDate(orders.getDistributionDate());
            detail.setCustomerId(orders.getCustomerId());
            detail.setOrderType(orders.getOrderType());
            if (isKitchen() == false)
                amountOfMoney = Arithmetic.add(detail.getTotal(),amountOfMoney,2) ;
        }
        if (isKitchen() == false) orders.setAmountOfMoney(amountOfMoney);//不是厨房
        List<Orders> ordersList = new ArrayList<>() ;
        ordersList.add(orders) ;
        dao.insertOrders(ordersList) ;
        if (ordersRecipeList != null) {
            dao.insertOrdersRecipe(ordersRecipeList);
            dao.insertOrdersRecipeDetails(ordersRecipeDetailsList);
        }
        int result = dao.insertOrdersDetail(data.getDetails()) ;
        if (result <= 0) return "生成订单失败" ;
        return null;
    }

    /**
     *
     * @param ordersDetail
     * @param id 食材id
     * @return
     */
    private OrdersDetail getOrdersDetail(List<OrdersDetail> ordersDetail,Long id) {
        for (OrdersDetail detail : ordersDetail) {
            if (detail.getFoodMaterialId().longValue() == id.longValue()) return detail ;
        }
        return null ;
    }

    private OrdersRecipe getOrdersRecipe(List<OrdersRecipe> ordersRecipe,Long id) {
        for (OrdersRecipe detail : ordersRecipe) {
            if (detail.getRecipeTemplateId().longValue() == id.longValue()) return detail ;
        }
        return null ;
    }

    /**
     * 修改订单的时候是否修改了数量
     */
    private void compareDetail(OrdersDetail newDetail,OrdersDetail oldDetail,StringBuilder sb) {
        if (newDetail.getTotalAmount().intValue() != oldDetail.getTotalAmount().intValue()) {
            sb.append("修改了食材[").append(oldDetail.getFoodMaterialName())
                    .append("]的数量，改前：")
                    .append(oldDetail.getTotalAmount())
                    .append("，改后：").append(newDetail.getTotalAmount()).append("；");
        }
    }

    private void compareDetail(OrdersRecipe newDetail,OrdersRecipe oldDetail,StringBuilder sb) {
        if (newDetail.getTotalAmount().intValue() != oldDetail.getTotalAmount().intValue()) {
            sb.append("修改了菜谱[").append(oldDetail.getRecipeTemplateName())
                    .append("]的数量，改前：")
                    .append(oldDetail.getTotalAmount())
                    .append("，改后：").append(newDetail.getTotalAmount()).append("；");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String modifyOrders(Orders orders) {
        List<OrdersDetail> details = orders.getDetail() ;
        OrdersDto dto = new OrdersDto() ;
        dto.setOrderId(orders.getId());
        List<Orders> orderList = dao.selectOrders(dto) ;
        if (orderList == null || orderList.isEmpty()) {
            return "你修改的订单已经被作废了" ;
        }
        Orders ordersCopy = orderList.get(0) ;
        SysUser userDetails = this.getSysUser();
        if (userDetails.getCustomerLogin() != null && ordersCopy.getOrderLock()) {
            return "订单已经被锁定，不能再进行修改";
        }
        if (ordersCopy.getOperationPerson() != null &&
                ordersCopy.getOperationPerson().longValue() != userDetails.getId().longValue()) {
            ordersCopy.setLastUpdatePerson(userDetails.getId());
            ordersCopy.setLastUpdateTime(new Date());
        } else {
            ordersCopy.setOperationDate(new Date());
        }
        ordersCopy.setMealPersons(orders.getMealPersons());
        List<OrdersRecipeDetails> ordersRecipeDetailsList = null;
        BigDecimal amountOfMoney = new BigDecimal("0.00") ;
        if (isKitchen()) { //处理厨房，产生食材明细
            List<OrdersRecipe> recipeList = orders.getRecipeDetail() ;
            ordersRecipeDetailsList = new ArrayList<>() ;
            Map<Long,OrdersDetail> ordersDetailMap = new HashMap<>() ;
            for (OrdersRecipe or : recipeList) {
                or.setId(nextId());
                or.setOrdersId(ordersCopy.getId());
                if (or.getEatDate() == null) {
                    or.setEatDate(ordersCopy.getEatDate());
                    or.setDistributionDate(ordersCopy.getDistributionDate());
                    or.setSupplyDate(ordersCopy.getSupplyDate());
                }
                or.setTotal(Arithmetic.mul(new BigDecimal(or.getTotalAmount()), or.getPrice(),2));
                or.setCustomerId(ordersCopy.getCustomerId());
                or.setMealsTypeId(ordersCopy.getMealsTypeId());
                or.setOrderType(ordersCopy.getOrderType());
                amountOfMoney = Arithmetic.add(or.getTotal(),amountOfMoney,2) ;
                for (OrdersRecipeDetails detail : or.getDetails()) {
                    if (ordersDetailMap.containsKey(detail.getFoodMaterialId())) {
                        OrdersDetail od = ordersDetailMap.get(detail.getFoodMaterialId()) ;
                        od.setTotalAmount(od.getTotalAmount() + or.getTotalAmount() * detail.getAmount());
                    } else {
                        OrdersDetail od = new OrdersDetail();
                        od.setOriginalProcess(detail.getOriginalProcess());
                        od.setAmount(detail.getAmount());
                        od.setSalePrice(detail.getSalePrice());
                        od.setBuyPrice(detail.getBuyPrice());
                        od.setFoodMaterialId(detail.getFoodMaterialId());
                        od.setTotalAmount(or.getTotalAmount() * detail.getAmount());
                        ordersDetailMap.put(detail.getFoodMaterialId(),od) ;
                    }
                    detail.setId(nextId());
                    detail.setOrdersId(ordersCopy.getId());
                    detail.setOrdersRecipeId(or.getId());
                    detail.setRecipeTemplateId(or.getRecipeTemplateId());
                    ordersRecipeDetailsList.add(detail) ;
                }
            }
            details = new ArrayList<>(ordersDetailMap.values());
            ordersCopy.setAmountOfMoney(amountOfMoney);
        }
        List<Long> list = new ArrayList<>() ;
        list.add(orders.getId());
        if (Constants.ORDER_STATUS_SUPPLY.equals(ordersCopy.getStatus())) {
            List<FoodMaterial> foodMaterials = dao.selectFoodMaterialAmount(list);
            if (orders.getRecipeDetail() != null) {
                for (FoodMaterial fm : foodMaterials) {
                    fm.setAmount(Arithmetic.div(fm.getAmount(),fm.getExpressionUnit(),3));
                }
            }
            Collections.sort(foodMaterials);
            foodMaterialDao.updateFoodMaterialStock(foodMaterials);//库存回加
        }

        StringBuilder sb = new StringBuilder() ;
        if (orders.getRecipeDetail() == null) {
            List<OrdersDetail> oldOrdersDetail = dao.selectOrdersDetail(orders.getId()) ;
            for (OrdersDetail oldDetail : oldOrdersDetail) {
                OrdersDetail findDetail = this.getOrdersDetail(details, oldDetail.getFoodMaterialId());
                if (findDetail != null) compareDetail(findDetail, oldDetail, sb);
                else {
                    sb.append("删除了食材[").append(oldDetail.getFoodMaterialName())
                            .append("]，数量是：").append(oldDetail.getTotalAmount())
                            .append("；");
                }
            }

            for (OrdersDetail newDetail : details) {
                OrdersDetail findDetail = this.getOrdersDetail(oldOrdersDetail, newDetail.getFoodMaterialId());
                if (findDetail == null) { //老明细中不存在的食材在新明细中存在
                    sb.append("添加了食材[").append(newDetail.getFoodMaterialName())
                            .append("]，数量是：").append(newDetail.getTotalAmount()).append("；");
                }
            }
        } else {
            List<OrdersRecipe> oldOrdersRecipe = dao.selectOrdersRecipe(orders.getId()) ;
            for (OrdersRecipe oldDetail : oldOrdersRecipe) {
                OrdersRecipe findDetail = this.getOrdersRecipe(orders.getRecipeDetail(), oldDetail.getRecipeTemplateId());
                if (findDetail == null) {
                    sb.append("删除了菜谱[").append(oldDetail.getRecipeTemplateName())
                            .append("]，数量是：").append(oldDetail.getTotalAmount()).append("；");
                } else {
                    compareDetail(findDetail, oldDetail, sb);
                }
            }

            for (OrdersRecipe newDetail : orders.getRecipeDetail()) {
                OrdersRecipe findDetail = this.getOrdersRecipe(oldOrdersRecipe, newDetail.getRecipeTemplateId());
                if (findDetail == null) { //老明细中不存在的食材在新明细中存在
                    sb.append("添加了菜谱[").append(newDetail.getRecipeTemplateName())
                            .append("]，数量是：").append(newDetail.getTotalAmount()).append("；");
                }
            }
        }

        if (sb.length() > 0) {
            DocumentTrack track = this.getDocumentTrack(orders.getId(),2,sb) ;
            documentTrackDao.insertDocumentTrack(track) ;
        }

        Collections.sort(list);
        dao.deleteOrdersDetail(list) ;
        for (OrdersDetail detail : details) {
            detail.setId(nextId());
            detail.setOrdersId(orders.getId());
            detail.setTotalAmount(detail.getTotalAmount()) ;
            detail.setTotal(Arithmetic.mul(detail.getSalePrice(),detail.getTotalAmount(),2));
            detail.setEatDate(ordersCopy.getEatDate());
            detail.setMealsTypeId(ordersCopy.getMealsTypeId());
            detail.setOrderType(ordersCopy.getOrderType());
            if (detail.getSupplyDate() == null)
                detail.setSupplyDate(ordersCopy.getSupplyDate());
            if (detail.getDistributionDate() == null)
                detail.setDistributionDate(ordersCopy.getDistributionDate());
            detail.setCustomerId(ordersCopy.getCustomerId());
            if (isKitchen() == false) amountOfMoney = Arithmetic.add(detail.getTotal(),amountOfMoney,2) ;
        }
        if (isKitchen() == false) ordersCopy.setAmountOfMoney(amountOfMoney);
        else {
            dao.deleteOrdersRecipe(ordersCopy.getId()) ;
            dao.deleteOrdersRecipeDetails(ordersCopy.getId()) ;
            dao.insertOrdersRecipe(orders.getRecipeDetail()) ;
            dao.insertOrdersRecipeDetails(ordersRecipeDetailsList) ;
        }
        dao.updateOrders(ordersCopy) ;
        if (Constants.ORDER_STATUS_SUPPLY.equals(ordersCopy.getStatus())) {
            List<FoodMaterial> fms = prepare(details);
            Collections.sort(fms);
            foodMaterialDao.updateFoodMaterialStock(fms);//库存回减
        }
        int rows = dao.insertOrdersDetail(details) ;
        if (rows > 0) return null;
        return "修改订单失败" ;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String removeOrders(Long orderId) {
        List<Long> ids = new ArrayList<>() ;
        ids.add(orderId) ;
        OrdersDto dto = new OrdersDto() ;
        dto.setOrderId(orderId);
        List<Orders> orders = dao.selectOrders(dto) ;
        if (orders.isEmpty()) return "你作废的订单不存在" ;
        if (Constants.ORDER_STATUS_SUPPLY.equals(orders.get(0).getStatus())) {
            return "订单已经出库，不能作废" ;
        }
        orders.get(0).setLastUpdatePerson(this.getSysUser().getId());
        orders.get(0).setLastUpdateTime(new Date());
        dao.insertRemoveOrders(orders.get(0)) ;
        dao.insertRemoveOrdersDetail(orderId) ;
        dao.insertRemoveOrdersRecipe(orderId) ;
        dao.insertRemoveOrdersRecipeDetail(orderId) ;
        dao.deleteOrdersDetail(ids) ;
        dao.deleteOrdersRecipe(orderId) ;
        dao.deleteOrdersRecipeDetails(orderId) ;
        int row = dao.deleteOrders(ids);
        return row > 0 ? null : "订单作废失败" ;
    }

    @Override
    public List<Orders> queryOrders(OrdersDto dto) {
        Boolean flag = dto.getUpdateSelf() ;
        if (flag != null && flag) {
            dto.setOperationPerson(this.getSysUser().getId());
        }
        return dao.selectOrders(dto);
    }

    @Override
    public List<OrdersCount> queryOrdersCount() {
        return dao.selectOrdersCount(this.getCurrentDate());
    }

    @Override
    public List<Orders> queryRemoveOrders(OrdersDto dto) {
        return dao.selectRemoveOrders(dto);
    }

    @Override
    public int removeCustomerTeamDetailsByDetailId(Long id) {
        return dao.deleteCustomerTeamDetailsByDetailId(id);
    }

    @Override
    public int addCustomerTeamDetails(CustomerTeamDetails customerTeamDetails) {
        List<CustomerTeamDetails> data = new ArrayList<>() ;
        customerTeamDetails.setId(nextId());
        data.add(customerTeamDetails) ;
        return dao.insertCustomerTeamDetails(data);
    }

    @Override
    public List<OrdersDetail> queryOrdersDetail(Long id) {
        return dao.selectOrdersDetail(id);
    }

    @Override
    public List<OrdersRecipe> queryOrdersRecipe(Long id) {
        return dao.selectOrdersRecipe(id);
    }

    @Override
    public List<OrdersDetail> queryRemoveOrdersDetail(Long id) {
        return dao.selectRemoveOrdersDetail(id);
    }

    @Override
    public List<OrdersRecipe> queryRemoveOrdersRecipe(Long ordersId) {
        return dao.selectRemoveOrdersRecipe(ordersId) ;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String copyOrders(OrdersDto dto) {
        OrdersDto tmp = new OrdersDto() ;
        tmp.setOrderId(dto.getOrderId());
        Orders orders = dao.selectOrders(tmp).get(0) ;
        orders.setEatDate(DateUtil.parse(dto.getEatDate()));
        Date currentDate = DateUtil.parse(this.getCurrentDate());
        if (orders.getEatDate().before(currentDate)) return "就餐日期要大于等于系统当前日期";//复制订单，就餐日期至少是今天
        OrderAction.TempOrderData orderData = new OrderAction.TempOrderData() ;

        if (dto.getCustomerId() != null && !dto.getCustomerId().isEmpty() &&
                dto.getCustomerId().get(0).longValue() != -1) {
            orderData.setCustomerId(dto.getCustomerId().get(0));
            orders.setCustomerId(orderData.getCustomerId());
        } else {
            orderData.setCustomerId(orders.getCustomerId());
        }
        if (StringUtils.isEmpty(dto.getMealsTypeId()))
            orderData.setMealsTypeId(orders.getMealsTypeId());
        else {
            orderData.setMealsTypeId(Long.valueOf(dto.getMealsTypeId()));
            CustomerInfoDto customerInfoDto = new CustomerInfoDto() ;
            customerInfoDto.setId(orderData.getCustomerId());
            customerInfoDto.setMealsTypeId(orderData.getMealsTypeId());
            List<CustomerInfo> customerInfos = customerDao.selectCustomerInfo(customerInfoDto) ;
            if (customerInfos == null || customerInfos.isEmpty()) return "客户没有设置此餐别";
            orders.setMealsTypeId(orderData.getMealsTypeId());
            orders.setMealPersons(customerInfos.get(0).getMealPersons());
            orders.setMealStandard(new BigDecimal(customerInfos.get(0).getMealStandard()));
        }
        orderData.setEatDate(orders.getEatDate());
        String checkResult = this.checkOrdersExist(orderData) ;
        if (checkResult != null) return checkResult ;

        List<OrdersDetail> details = dao.selectOrdersDetail(dto.getOrderId()) ;
        List<OrdersRecipe> ordersRecipesList = dao.selectOrdersRecipe(orders.getId()) ;
        orders.setId(nextId());
        List<Long> cs = new ArrayList<>() ;
        cs.add(orders.getCustomerId()) ;
        CustomerInfo customerInfo = customerDao.selectCustomerInfoByIds(cs).get(0);
        orders.setSupplyDate(DateUtil.plus(orders.getEatDate(),customerInfo.getAheadTime() * -1));
        orders.setDistributionDate(DateUtil.plus(orders.getSupplyDate() , -1));
        if (!Constants.ORDER_TYPE_SELF.equals(orders.getOrderType())) {
            orders.setOperationPerson(this.getSysUser().getId());
        }
        orders.setOperationDate(new Date());
        orders.setLastUpdateTime(null);
        orders.setLastUpdatePerson(null);
        orders.setStatus(Constants.ORDER_STATUS_NORMAL);
        for (OrdersDetail od : details) {
            od.setId(nextId());
            od.setOrdersId(orders.getId());
            od.setEatDate(orders.getEatDate());
            od.setMealsTypeId(orders.getMealsTypeId());
            od.setSupplyDate(orders.getSupplyDate());
            od.setDistributionDate(orders.getDistributionDate());
            od.setCustomerId(orders.getCustomerId());
            od.setOrderType(orders.getOrderType());
        }
        List<Orders> list = new ArrayList<>();
        list.add(orders) ;
        dao.insertOrders(list) ;
        if (isKitchen()) {
            List<OrdersRecipeDetails> ordersRecipeDetailsList = new ArrayList<>() ;
            for (OrdersRecipe or : ordersRecipesList) {
                or.setId(nextId());
                or.setOrdersId(orders.getId());
                or.setEatDate(orders.getEatDate());
                or.setDistributionDate(orders.getDistributionDate());
                or.setSupplyDate(orders.getSupplyDate());
                for (OrdersRecipeDetails detail : or.getDetails()) {
                    detail.setId(nextId());
                    detail.setOrdersId(orders.getId());
                    detail.setOrdersRecipeId(or.getId());
                    ordersRecipeDetailsList.add(detail) ;
                }
            }
            dao.insertOrdersRecipe(ordersRecipesList) ;
            dao.insertOrdersRecipeDetails(ordersRecipeDetailsList) ;
        }
        int result = dao.insertOrdersDetail(details);
        if (result == 0) return "订单复制失败" ;
        return null ;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String batchModifyOrdersPrice(BatchModifyOrdersPriceDto dto) {
        int result = 0 ;
        if (isKitchen() == false) {
            if (dto.getVip()) {
                result = dao.batchUpdateVipOrdersPrice(dto);
                if (result > 0) dao.batchUpdateVipOrdersMoney(dto);
            } else {
                result = dao.batchUpdateOrdersPrice(dto);
                if (result > 0) dao.batchUpdateOrdersMoney(dto);
            }
        } else {
            if (dto.getVip()) {
                result = dao.batchUpdateRecipeVipOrdersPrice(dto);
                if (result > 0) dao.batchUpdateRecipeVipOrdersMoney(dto);
            } else {
                result = dao.batchUpdateRecipeOrdersPrice(dto);
                if (result > 0) dao.batchUpdateRecipeOrdersMoney(dto);
            }
        }
        return result > 0 ? null : "没有符合条件的订单";
    }

    @Override
    public List<Orders> queryTrackOrders(TrackOrdersDto dto) {
        return dao.selectTrackOrders(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String supplyOutWareHouse(List<Long> orderIds) {
        if (orderIds == null || orderIds.isEmpty()) return "请选择要配送出库的订单再操作" ;
        List<Orders> orders = dao.selectOrdersStatus(orderIds) ;
        for (Orders o : orders) {
            if (!Constants.ORDER_STATUS_NORMAL.equals(o.getStatus())) {
                return "编号[" + o.getId() + "]的订单已经出库，请重新选择" ;
            }
        }
        Collections.sort(orderIds);
        List<FoodMaterial> foodMaterials = dao.selectFoodMaterialAmount(orderIds) ;
        Collections.sort(foodMaterials);
        if (isKitchen())
            for (FoodMaterial fm : foodMaterials) {
                fm.setAmount(Arithmetic.div(fm.getAmount(),fm.getExpressionUnit(),3));
            }
        foodMaterialDao.updateFoodMaterialStock(foodMaterials) ;//扣库存
        int result = dao.batchUpdateOrdersStatus(orderIds) ;
        if (result == 0) return "配送出库不成功" ;
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Orders> print(List<Long> ordersIds,List<String> remarks) {
        List<Orders> result = isKitchen() ? dao.selectRecipePrintOrders(ordersIds) : dao.selectPrintOrders(ordersIds);
        for (int i = 0 ; i < result.size() ; i++) {
            result.get(i).setRemark(remarks.get(i));
        }
        dao.updateOrdersPrintStatus(result) ;
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int lockOrders(LockOrderDto params) {
        return dao.lockOrders(params);
    }

    class TempCustomer {

        public TempCustomer(String name, int showOrder) {
            this.name = name;
            this.showOrder = showOrder;
        }
        String name ;
        int showOrder ;
    }

    class TreeSetCompare implements Comparator{

        @Override
        public int compare(Object o1, Object o2) {
            TempCustomer tc1 = (TempCustomer)o1;
            TempCustomer tc2 = (TempCustomer)o2;
            if (tc1.showOrder > tc2.showOrder) return 1 ;
            else if (tc1.showOrder < tc2.showOrder) return -1 ;
            else return 0;
        }
    }

    private void querySupplySummaryByRouterSum(List<Map<String,Object>> result,StringBuilder sb,
                  List<CustomerInfo> customers,OrderAction.SupplySummary ss,int sum) {
        if (result.size() != 0) result.get(result.size() - 1).put("total", sum);
        List<String> headers = new ArrayList<>();
        for (CustomerInfo ci : customers) {
            sb.setLength(0);
            sb.append(ci.getName()).append('-').append(ci.getShowOrder());
            headers.add(sb.toString());
        }
        ss.setHeader(headers);
    }

    private void customerJoinOrder(List<CustomerInfo> customers,StringBuilder sb,Map<String,Object> tmp) {
        for (CustomerInfo ci : customers) {
            sb.setLength(0);
            sb.append(ci.getName()).append('-').append(ci.getShowOrder());
            tmp.put(sb.toString(), null);
        }
    }

    @Override
    public OrderAction.SupplySummary querySupplySummaryByRouter(SupplySummaryBySupplyDto dto) {
        OrderAction.SupplySummary ss = new OrderAction.SupplySummary() ;
        boolean kitchen = this.getSysUser().getFoodSupplyType().equals(Constants.KITCHEN_FOOD) ;
        //TreeSet<TempCustomer> treeSet = new TreeSet<>(new TreeSetCompare()) ;
        CustomerInfoDto where = new CustomerInfoDto();
        where.setRouterId(dto.getRouter());
        List<CustomerInfo> customers = customerDao.selectCustomerInfo(where) ;
        List<OrdersDetail> details = kitchen == false ?dao.selectSupplySummaryByRouter(dto) : null;
        List<OrdersRecipe> recipes = kitchen ? dao.selectRecipeSupplySummaryByRouter(dto) : null;
        List<Map<String,Object>> result = new ArrayList<>() ;
        long foodId = -1 ;
        int sum = 0 ;
        Map<String,Object> tmp = null ;
        StringBuilder sb = new StringBuilder() ;
        if (kitchen == false) {
            for (OrdersDetail detail : details) {
                if (foodId != detail.getFoodMaterialId().longValue()) {
                    if (result.size() != 0) tmp.put("total", sum);
                    tmp = new HashMap<>();
                    sum = 0;
                    result.add(tmp);
                    tmp.put("foodMaterialId", detail.getFoodMaterialId());
                    tmp.put("name", detail.getFoodMaterialName());
                    tmp.put("unitName", detail.getUnitName());
                    customerJoinOrder(customers,sb,tmp) ;
                    sb.setLength(0);
                    sb.append(detail.getCustomerName()).append('-').append(detail.getShowOrder());
                    tmp.put(sb.toString(), detail.getTotalAmount());
                    sum += detail.getTotalAmount().intValue();
                    foodId = detail.getFoodMaterialId().longValue();
                } else {
                    sb.setLength(0);
                    sb.append(detail.getCustomerName()).append('-').append(detail.getShowOrder());
                    tmp.put(sb.toString(), detail.getTotalAmount());
                    sum += detail.getTotalAmount().intValue();
                }
            }
            querySupplySummaryByRouterSum(result,sb,customers,ss,sum) ;
        } else {
            for (OrdersRecipe recipe : recipes) {
                if (foodId != recipe.getRecipeTemplateId().longValue()) {
                    if (result.size() != 0) tmp.put("total", sum);
                    tmp = new HashMap<>();
                    sum = 0;
                    result.add(tmp);
                    tmp.put("recipeTemplateId", recipe.getRecipeTemplateId());
                    tmp.put("name", recipe.getRecipeTemplateName());
                    customerJoinOrder(customers,sb,tmp) ;
                    sb.setLength(0);
                    sb.append(recipe.getCustomerName()).append('-').append(recipe.getShowOrder());
                    tmp.put(sb.toString(), recipe.getTotalAmount() + "/" + recipe.getTotalWeight());
                    sum += recipe.getTotalAmount().intValue();
                    foodId = recipe.getRecipeTemplateId().longValue();
                } else {
                    sb.setLength(0);
                    sb.append(recipe.getCustomerName()).append('-').append(recipe.getShowOrder());
                    tmp.put(sb.toString(), recipe.getTotalAmount() + "/" + recipe.getTotalWeight());
                    sum += recipe.getTotalAmount().intValue();
                }
            }
            querySupplySummaryByRouterSum(result,sb,customers,ss,sum) ;
        }
        ss.setData(result);
        return ss;
    }

    @Override
    public List<FoodMaterial> queryShowPrintLabel(SupplySummaryBySupplyDto dto) {
        return dao.selectShowPrintLabel(dto);
    }

    @Override
    public List<RecipeTemplate> queryRecipeShowPrintLabel(SupplySummaryBySupplyDto dto) {
        return dao.selectRecipeShowPrintLabel(dto);
    }

    @Override
    public List<OrdersDetail> queryPrintLabel(SupplySummaryBySupplyDto dto) {
        return dao.selectPrintLabel(dto);
    }

    @Override
    public List<OrdersRecipe> queryRecipePrintLabel(SupplySummaryBySupplyDto dto) {
        return dao.selectRecipePrintLabel(dto);
    }

    @Override
    public OrderAction.SupplySummary querySupplySummaryBySupplier(SupplySummaryBySupplierDto params) {
        OrderAction.SupplySummary ss = new OrderAction.SupplySummary() ;
        CustomerInfoDto where = new CustomerInfoDto();
        where.setRouterId(params.getRouter());
        List<CustomerInfo> customers = customerDao.selectCustomerInfo(where) ;
        List<OrdersDetail> details = dao.selectSupplySummaryBySupplier(params) ;
        List<Map<String,Object>> result = new ArrayList<>() ;
        int sum = 0 ;
        String supplierName = null ;
        Map<String,Object> tmp = null ;
        StringBuilder sb = new StringBuilder() ;
        for (OrdersDetail detail : details) {
            if (!detail.getSupplierName().equals(supplierName)) {
                if (result.size() != 0) tmp.put("total",sum) ;
                tmp = new HashMap<>() ;
                sum = 0 ;
                result.add(tmp) ;
                tmp.put("unitName",detail.getUnitName()) ;
                tmp.put("supplierName",detail.getSupplierName()) ;
                customerJoinOrder(customers,sb,tmp) ;
                tmp.put("label",detail.getLabel()) ;
                sb.setLength(0);
                sb.append(detail.getCustomerName()).append('-').append(detail.getShowOrder());
                tmp.put(sb.toString(),detail.getTotalAmount()) ;
                sum += detail.getTotalAmount().intValue() ;
                supplierName = detail.getSupplierName() ;
            } else {
                sb.setLength(0);
                sb.append(detail.getCustomerName()).append('-').append(detail.getShowOrder());
                tmp.put(sb.toString(),detail.getTotalAmount()) ;
                sum += detail.getTotalAmount().intValue() ;
            }
        }
        querySupplySummaryByRouterSum(result,sb,customers,ss,sum) ;
        return ss;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchModifyOrdersDistributionDate(BatchModifyOrdersDistributionDateDto dto) {
        if (dto.getMealsTypeId().size() == 1) {
            if (dto.getMealsTypeId().get(0).longValue() == -1) dto.setMealsTypeId(null);
        }
        Date distributionDate = DateUtil.parse(dto.getDistributionDate(),Constants.DEFAULT_DATE_FORMAT) ;
        dto.setSupplyDate(DateUtil.format(DateUtil.plus(distributionDate,1),Constants.DEFAULT_DATE_FORMAT));
        List<OrdersDetail> details = dao.selectBatchOrdersDetailDistributionDate(dto) ;
        if (details == null || details.size() == 0) return 0 ;
        StringBuilder sb = new StringBuilder() ;
        List<DocumentTrack> documentTracks = new ArrayList<>() ;
        long ordersId = details.get(0).getOrdersId() ;
        for (OrdersDetail detail : details) {
            if (ordersId != detail.getOrdersId().longValue()) {
                ordersId = detail.getOrdersId().longValue() ;
                DocumentTrack documentTrack = this.getDocumentTrack(ordersId,2,sb) ;
                documentTracks.add(documentTrack) ;
                sb.setLength(0);
            }
            sb.append("食材【").append(detail.getFoodMaterialName()).append("】配货日期被修改，")
                    .append("改前：").append(DateUtil.format(detail.getDistributionDate(),Constants.DEFAULT_DATE_FORMAT))
                    .append("，改后：").append(distributionDate).append("；");
        }
        DocumentTrack documentTrack = this.getDocumentTrack(ordersId,2,sb) ;
        documentTracks.add(documentTrack) ;
        documentTrackDao.batchInsertDocumentTrack(documentTracks) ;
        return dao.batchUpdateOrdersDetailDistributionDate(dto);
    }

    @Override
    public OrderAction.SupplySummary queryOrderDetailsByDistributionDateAndRouter(DistributionDateAndRouterDto dto) {
        OrderAction.SupplySummary ss = new OrderAction.SupplySummary() ;
        CustomerInfoDto where = new CustomerInfoDto();
        where.setRouterId(dto.getRouter());
        List<CustomerInfo> customers = customerDao.selectCustomerInfo(where) ;
        dto.setFoodSupplyType(getSysUser().getFoodSupplyType());
        List<OrdersDetail> details = dao.selectOrderDetailsByDistributionDateAndRouter(dto) ;
        List<Map<String,Object>> result = new ArrayList<>() ;
        long foodId = -1,mealsId = -1 ;
        Map<String,Object> tmp = null ;
        for (OrdersDetail detail : details) {
            if (foodId != detail.getFoodMaterialId().longValue()) {
                tmp = new HashMap<>() ;
                result.add(tmp) ;
                tmp.put("mealsTypeName",detail.getMealsTypeName()) ;
                tmp.put("foodMaterialName",detail.getFoodMaterialName()) ;
                for (CustomerInfo ci : customers) {
                    tmp.put(ci.getName(),null) ;
                }
                tmp.put(detail.getCustomerName(),detail.getTotalAmount()) ;
                foodId = detail.getFoodMaterialId().longValue() ;
            } else {
                tmp.put(detail.getCustomerName(),detail.getTotalAmount()) ;
            }
        }
        ss.setData(result);
        List<String> headers = new ArrayList<>() ;
        for (CustomerInfo ci : customers) {
            headers.add(ci.getName()) ;
        }
        ss.setHeader(headers);
        return ss;
    }

    @Override
    public List<Map<String, Object>> queryReminder(ReminderDto reminderDto) {
        Date date = DateUtil.plus(new Date(),7) ;
        int week = DateUtil.getWeek(date).getValue() ;
        Date begin = reminderDto.getBeginEatDate() == null ?
                DateUtil.plus(date,(week - 1) * -1) :
                DateUtil.parse(reminderDto.getBeginEatDate(),Constants.DEFAULT_DATE_FORMAT);
        Date end = reminderDto.getEndEatDate() == null ?
                DateUtil.plus(date,7 - week) :
                DateUtil.parse(reminderDto.getEndEatDate(),Constants.DEFAULT_DATE_FORMAT);
        reminderDto.setBeginEatDate(this.getDate(begin));
        reminderDto.setEndEatDate(this.getDate(end));
        reminderDto.setDay1(this.getDate(begin));
        reminderDto.setDay2(this.getDate(DateUtil.plus(begin,1)));
        reminderDto.setDay3(this.getDate(DateUtil.plus(begin,2)));
        reminderDto.setDay4(this.getDate(DateUtil.plus(begin,3)));
        reminderDto.setDay5(this.getDate(DateUtil.plus(begin,4)));
        reminderDto.setDay6(this.getDate(DateUtil.plus(begin,5)));
        reminderDto.setDay7(this.getDate(DateUtil.plus(begin,6)));
        List<Map<String, Object>> result = dao.selectReminder(reminderDto);
        return result ;
    }

    @Override
    public List<Map<String, Object>> queryExceed(ExceedDto dto) {
        if (dto.getRecipe().booleanValue()) return dao.selectRecipeExceed(dto);
        else return dao.selectExceed(dto);
    }

    @Override
    public List<FoodProduct> foodProduct(FoodProductDto dto) {
        List<FoodProduct> result = dao.foodProduct(dto) ;
        long recipeTemplateId = -1 ;
        for (FoodProduct foodProduct : result) {
            if (recipeTemplateId != foodProduct.getRecipeTemplateId().longValue()) {
                recipeTemplateId = foodProduct.getRecipeTemplateId().longValue() ;
            } else {
                foodProduct.setMealsTypeName("");
                foodProduct.setRecipeTemplateName("");
                foodProduct.setRecipeAmount(null);
                foodProduct.setTotalWeight(null);
            }
        }
        return result;
    }
}
